package main

import (
	"bytes"
	"flag"
	"fmt"
	"go/ast"
	"go/format"
	"io/ioutil"
	"strings"
	"text/template"

	"github.com/wzshiming/gotype"
)

type m struct {
	Name    string
	Doc     string
	Comment string
}

var (
	i = flag.String("i", "", "Input package path")
	p = flag.String("p", "", "Package name")
	o = flag.String("o", "", "Out file")
)

func init() {
	flag.Parse()
}

func main() {
	imp := gotype.NewImporter()
	n, err := imp.Import(*i, "")
	if err != nil {
		fmt.Println(err)
		return
	}

	ts := []m{}
	vs := []m{}
	fs := []m{}

	nc := n.NumChild()
	for i := 0; i != nc; i++ {
		v := n.Child(i)
		if ast.IsExported(v.Name()) {
			switch v.Kind() {
			case gotype.Declaration:
				decl := v.Declaration()

				switch decl.Kind() {
				default:
					vs = append(vs, m{
						Name:    v.Name(),
						Doc:     comment(v.Doc().Text()),
						Comment: comment(v.Comment().Text()),
					})
				case gotype.Func:
					fs = append(fs, m{
						Name:    v.Name(),
						Doc:     comment(v.Doc().Text()),
						Comment: comment(v.Comment().Text()),
					})
				}

			case gotype.Scope, gotype.Invalid:
			// No action
			default:
				doc := v
				ts = append(ts, m{
					Name:    v.Name(),
					Doc:     comment(doc.Doc().Text()),
					Comment: comment(doc.Comment().Text()),
				})
			}
		}
	}

	buf := bytes.NewBuffer(nil)

	if *p == "" {
		*p = n.Name()
	}
	fn := *o
	if fn == "" {
		fn = (*p)
	}

	templateFile.ExecuteTemplate(buf, "temp", map[string]interface{}{
		"PackageName": p,
		"Origin":      i,
		"TypeSpec":    ts,
		"ValueSpec":   vs,
		"FuncSpec":    fs,
		"Filename":    fn,
	})

	d, err := format.Source([]byte(buf.String()))
	if err != nil {
		fmt.Println(buf.String(), err)
		return
	}

	if *o == "" {
		fmt.Print(string(d))
	} else {
		ioutil.WriteFile(*o, d, 0666)
	}
}

func comment(s string) string {
	ss := []string{}
	dd := strings.Split(s, "\n")
	for i, v := range dd {
		if v == "" && i == len(dd)-1 {
			continue
		}
		v = strings.TrimSpace(v)
		if strings.Index(v, "//") != 0 {
			v = "// " + v
		}
		ss = append(ss, v)
	}

	return strings.Join(ss, "\n")
}

var templateFile = template.New("temp")

func init() {
	templateFile.Parse(temp)
}

var temp = `// Code generated by "pkgimport -p {{.PackageName}} -i {{.Origin}} -o {{.Filename}}"; DO NOT EDIT.
// Install by "go get -u -v github.com/wzshiming/gotype/cmd/pkgimport";
//go:generate pkgimport -p {{.PackageName}} -i {{.Origin}} -o {{.Filename}}

package {{.PackageName}}

import (
	origin "{{.Origin}}"
)

{{if .ValueSpec}}
// Value
var (
	{{range .ValueSpec}}
	{{.Doc}}
	{{.Name}} = origin.{{.Name}} {{.Comment}}
	{{end}}
)
{{end}}

{{if .TypeSpec}}
// Type
type (
	{{range .TypeSpec}}
	{{.Doc}}
	{{.Name}} = origin.{{.Name}} {{.Comment}}
	{{end}}
)
{{end}}

{{if .FuncSpec}}
// Function
var (
	{{range .FuncSpec}}
	{{.Doc}}
	{{.Name}} = origin.{{.Name}} {{.Comment}}
	{{end}}
)
{{end}}

`
